#include "apdu_cryption_manager.h"

#include "../../mk_lib/mk_utility.h"

#include <string.h>
#include <memory.h>
#include <stdlib.h>

apdu_cryption_manager::apdu_cryption_manager( void )
{

}

apdu_cryption_manager::~apdu_cryption_manager( void )
{

}

apdu * apdu_cryption_manager::create_apdu_encrypt_init( int app_id, int container_id, unsigned long key_id,
													   unsigned char * iv, int iv_len,
													   unsigned long padding_type, unsigned long feed_bit_len )
{
	apdu * newApdu = new apdu(SC_APDU_CASE_3_EXT, 0x80, 0xA4, 0,0x00, "EncryptInit");

	unsigned char data[4096] = {0};

	int pos = 0;
	mk_utility::fill_buff_with_word_value_be(app_id, data);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(container_id, data + pos);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(key_id, data + pos);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(iv_len, data + pos);
	pos += 2;

	memcpy(data + pos, iv, iv_len);
	pos += iv_len;

	mk_utility::fill_buff_with_dword_value_be(padding_type, data + pos);
	pos += 4;
	
	mk_utility::fill_buff_with_dword_value_be(feed_bit_len, data + pos);
	pos += 4;

	newApdu->set_lc_data(data, pos);

	return newApdu;
}

apdu * apdu_cryption_manager::create_apdu_encrypt( int app_id, int container_id, unsigned long key_id, 
												  unsigned char * input, int input_len )
{
	apdu * newApdu = new apdu(SC_APDU_CASE_4_EXT, 0x80, 0xA6, 0,0x00, "Encrypt");

	unsigned char data[4096] = {0};

	int pos = 0;
	mk_utility::fill_buff_with_word_value_be(app_id, data);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(container_id, data + pos);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(key_id, data + pos);
	pos += 2;

	memcpy(data + pos, input, input_len);
	pos += input_len;

	newApdu->set_lc_data(data, pos);

	return newApdu;
}

apdu * apdu_cryption_manager::create_apdu_encrypt_update( int app_id, int container_id, unsigned long key_id, 
														unsigned char * input, int input_len )
{
	apdu * newApdu = new apdu(SC_APDU_CASE_4_EXT, 0x80, 0xA8, 0,0x00, "EncryptUpdate");

	unsigned char data[4096] = {0};

	int pos = 0;
	mk_utility::fill_buff_with_word_value_be(app_id, data);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(container_id, data + pos);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(key_id, data + pos);
	pos += 2;

	memcpy(data + pos, input, input_len);
	pos += input_len;

	newApdu->set_lc_data(data, pos);

	return newApdu;
}

apdu * apdu_cryption_manager::create_apdu_encrypt_final( int app_id, int container_id, unsigned long key_id,
														unsigned char * input, int input_len )
{
	apdu * newApdu = new apdu(SC_APDU_CASE_4_EXT, 0x80, 0xAA, 0,0x00, "EncryptFinal");

	unsigned char data[4096] = {0};

	int pos = 0;
	mk_utility::fill_buff_with_word_value_be(app_id, data);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(container_id, data + pos);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(key_id, data + pos);
	pos += 2;

	memcpy(data + pos, input, input_len);
	pos += input_len;

	newApdu->set_lc_data(data, pos);

	return newApdu;
}

apdu * apdu_cryption_manager::create_apdu_decrypt_init( int app_id, int container_id, unsigned long key_id, 
													   unsigned char * iv, int iv_len,
													   unsigned long padding_type, unsigned long feed_bit_len )
{
	apdu * newApdu = new apdu(SC_APDU_CASE_4_EXT, 0x80, 0xAC, 0,0x00, "DecryptInit");

	unsigned char data[4096] = {0};

	int pos = 0;
	mk_utility::fill_buff_with_word_value_be(app_id, data);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(container_id, data + pos);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(key_id, data + pos);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(iv_len, data + pos);
	pos += 2;

	memcpy(data + pos, iv, iv_len);
	pos += iv_len;

	mk_utility::fill_buff_with_dword_value_be(padding_type, data + pos);
	pos += 4;

	mk_utility::fill_buff_with_dword_value_be(feed_bit_len, data + pos);
	pos += 4;

	newApdu->set_lc_data(data, pos);

	return newApdu;
}

apdu * apdu_cryption_manager::create_apdu_decrypt( int app_id, int container_id, unsigned long key_id, 
												  unsigned char * input, int input_len )
{
	apdu * newApdu = new apdu(SC_APDU_CASE_4_EXT, 0x80, 0xAE, 0,0x00, "Decrypt");

	unsigned char data[4096] = {0};

	int pos = 0;
	mk_utility::fill_buff_with_word_value_be(app_id, data);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(container_id, data + pos);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(key_id, data + pos);
	pos += 2;

	memcpy(data + pos, input, input_len);
	pos += input_len;

	newApdu->set_lc_data(data, pos);

	return newApdu;
}

apdu * apdu_cryption_manager::create_apdu_decrypt_update( int app_id, int container_id, unsigned long key_id, 
														unsigned char * input, int input_len )
{
	apdu * newApdu = new apdu(SC_APDU_CASE_4_EXT, 0x80, 0xB0, 0,0x00, "DecryptUpdate");

	unsigned char data[4096] = {0};

	int pos = 0;
	mk_utility::fill_buff_with_word_value_be(app_id, data);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(container_id, data + pos);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(key_id, data + pos);
	pos += 2;

	memcpy(data + pos, input, input_len);
	pos += input_len;

	newApdu->set_lc_data(data, pos);

	return newApdu;
}

apdu * apdu_cryption_manager::create_apdu_decrypt_final( int app_id, int container_id, unsigned long key_id, 
														unsigned char * input, int input_len )
{
	apdu * newApdu = new apdu(SC_APDU_CASE_4_EXT, 0x80, 0xB2, 0,0x00, "DecryptFinal");

	unsigned char data[4096] = {0};

	int pos = 0;
	mk_utility::fill_buff_with_word_value_be(app_id, data);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(container_id, data + pos);
	pos += 2;

	mk_utility::fill_buff_with_word_value_be(key_id, data + pos);
	pos += 2;

	memcpy(data + pos, input, input_len);
	pos += input_len;

	newApdu->set_lc_data(data, pos);

	return newApdu;
}

